/*

*/

(function($) { 
$.fn.touchobject = function(settings) {
	var config = {
		disabled: false,
		cancel: ':input,option',
		containment: '',
		exclude: '',
		handle: false,
		event_callback: null,
		preventDefaultEvents: true
	};
	if (settings) $.extend(config, settings);
	var selector = this.selector;
	if (selector == '') return false;	
	if (config.handle != ''){
		var handle = config.handle;
	} else {
		var handle = selector;
	}	
	var handle_ident;
	var resize_ident;
	var touches = [];
	var object = null;
	var prev_border = '';
	var obj_pos = {x1:-1,y1:-1,x2:-1,y2:-1};
	// ##################################################
	function touchstart(t){
		if (touches.length == 1) {			
			if (handle != selector){
				object = $(t.target).closest(selector);
				$('body').bind('touchstart',function(){
					if (config.disabled) return;
					_touchstart(event,false);
					return false;
				});
				$('body').bind('touchmove',function(){
					if (config.disabled) return;
					_touchmove(event);
					return false;
				});
				$('body').bind('touchend',function(){
					if (config.disabled) return;
					_touchend(event);
					return false;
				});
				$('body').bind('touchcancel',function(){
					if (config.disabled) return;
					_touchend(event);
					return false;
				});				
			} else {
				object = $(t.target);
			}
			if (object.length == 1){
				handle_ident = t.identifier;				
				var p = object.position();
				obj_pos.x1 = p.left;
				obj_pos.y1 = p.top;
				prev_border = object.css('border');
				object.css('border','1px solid red');	
			}
			$(object).trigger('dragstart');
			// handle down
		} else if (touches.length == 2) {
			$(object).trigger('resizestart');
			obj_pos.x2 = object.width();
			obj_pos.y2 = object.height();			
			resize_ident = t.identifier;
		}
	}
	function touchmove(t){	
		var changed = false;
		var cp = object.position();	
		var pos = {x1:cp.left,
				y1:cp.top,
				x2:object.width(),
				y2:object.height()};
		if (handle_ident == t.identifier){
			var hdl = t.pageX - t.startPageX;
			var hdt = t.pageY - t.startPageY;
			pos.x1 = obj_pos.x1 + hdl;
			pos.y1 = obj_pos.y1 + hdt;
			changed = true;
		} else if(resize_ident == t.identifier){
			var hdl = t.pageX - t.startPageX;
			var hdt = t.pageY - t.startPageY;
			pos.x2 = obj_pos.x2 + hdl;
			pos.y2 = obj_pos.y2 + hdt;
			changed = true;
		}
		if (changed){
			if (config.containment !== false){
				if ($(config.containment).length == 1){
					if (pos.x1 < 0){
						pos.x1 = 0;
					}
					if (pos.y1 < 0){
						pos.y1 = 0;
					}
					if (pos.x2 + pos.x1 >= $(config.containment).width() - 1){
						if(handle_ident == t.identifier){
							pos.x1 = $(config.containment).width() - pos.x2;
							pos.x1 -= 2;
						} else {
							pos.x2 = $(config.containment).width() - pos.x1;
							pos.x2 -= 2;
						}
					}
					if (pos.y2 + pos.y1 >= $(config.containment).height() - 1){
						if(handle_ident == t.identifier){
							pos.y1 = $(config.containment).height() - pos.y2;
							pos.y1 -= 2;
						} else {
							pos.y2 = $(config.containment).height() - pos.y1;
							pos.y2 -= 2;
						}
					}
				}
			}
			if(handle_ident == t.identifier){
				object.css('left',pos.x1 + 'px');
				object.css('top',pos.y1 + 'px');
			} else {
				object.css('width',pos.x2 + 'px');
				object.css('height',pos.y2 + 'px');
			}
		}		
	}
	function touchend(t){
		if (handle_ident == t.identifier){
			$(object).trigger('dragstop');
			object.css('border',prev_border);
			if (handle != selector){
				$('body').unbind('touchstart');
				$('body').unbind('touchmove');
				$('body').unbind('touchend');
				$('body').unbind('touchcancel');
				setupHandleEvents();
			}			
			object = null;
			handle_ident = null;
			resize_ident = null;
		} else if(resize_ident == t.identifier){
			$(object).trigger('resizestop');
		}
	}	
	// ##################################################
	function checkTouches(all_touches){
		// loop thru touches to see what ones are no longer active
		var toRemove = [];
		for (var i = 0; i < touches.length; i++){
			var found = false;
			for (var j = 0; j < all_touches.length; j++ ){
				if (touches[i].identifier == all_touches[j].identifier){
					found = true;
				}
			}
			if (!found){
				toRemove.push({identifier:touches[i].identifier});
			}
		}	
		// remove inactive touches
		for (var i = 0; i < toRemove.length; i++){
			j = touchIndex(toRemove[i].identifier);
			if (j > -1){
				var t = touches[j];
				touches.splice(j ,1);
				touchend(t);
			}
		}
	}
	function touchIndex(identifier){
		for (var j = 0 ; j < touches.length; j++){
			if (touches[j].identifier == identifier){
				return j;
			}
		}
		return -1;
	}
	function getTickCount(){
		var now = new Date();
	    return now.getTime();
	}
	function getTouch(identifier){
		for (var j = 0 ; j < touches.length; j++){
			if (touches[j].identifier == identifier){
				return touches[j];
			}
		}
		return null;
	}	
	// ##########################################################
	function _touchstart(event,ishandle){
		var allTouches = event.touches;
		for (var i = 0; i < allTouches.length; i++){
			if (touchIndex(allTouches[i].identifier) == -1){	
				var touch = allTouches[i];		
				var starttick = getTickCount();
				var t = {identifier:touch.identifier,
						pageX:touch.pageX,
						pageY:touch.pageY,
						startPageX:touch.pageX,
						startPageY:touch.pageY,
						starttick:starttick,
						target:$(event.target),
						ishandle:ishandle};
				touches.push(t);
				touchstart(t);				
			}
		}
	}
	function _touchmove(event){
		var allTouches = event.touches;
		for (var i = 0; i < allTouches.length; i++){
			var touch = allTouches[i];
			var j = touchIndex(touch.identifier);
			// is it in our touches array?
			if (j > -1){
				// has it moved?
				if (touches[j].pageX != touch.pageX || touches[j].pageY != touch.pageY){
					// this touch has moved
					touches[j].pageX = touch.pageX;
					touches[j].pageY = touch.pageY;
					touchmove(touches[j]);
				}
			}
		}
	}
	function _touchend(event){
		var allTouches = event.touches;
		checkTouches(allTouches);		
	}	
	function setupHandleEvents(){
		// #####################################  Main  #####################################	
		$('body').delegate(handle,'touchstart', function() {
			//$(selector).bind('touchstart', function() {
			if (config.disabled) return;
			if (config.exclude != '' && $(event.target).is(config.exclude)){
				return true;
			}
			_touchstart(event,true);
			//return false;
			event.preventDefault();
		});
		$('body').delegate(handle,'touchmove', function() {
			//$(selector).bind('touchmove', function() {
			if (config.disabled) return;
			_touchmove(event);
			//return false;
			event.preventDefault();
		});
		$('body').delegate(handle,'touchend', function() {
			//$(selector).bind('touchend', function() {
			if (config.disabled) return;
			_touchend(event);
			//return false;
			event.preventDefault();
		});	
	}
	setupHandleEvents();
	return this;
};
})(jQuery);